/*
* jQuery SimpleTree Drag&Drop plugin
* Update on 22th May 2008
* Version 0.3
*
* Licensed under BSD <http://en.wikipedia.org/wiki/BSD_License>
* Copyright (c) 2008, Peter Panov <panov@elcat.kg>, IKEEN Group http://www.ikeen.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of the Peter Panov, IKEEN Group nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Peter Panov, IKEEN Group ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Peter Panov, IKEEN Group BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


$.fn.simpleTree = function(opt){
	
	
	return this.each(function(){
		var TREE = this;
		var ROOT = $('.root',this);
		var mousePressed = false;
		var mouseMoved = false;
		var dragMoveType = false;
		var dragNode_destination = false;
		var dragNode_source = false;
		var dragDropTimer = false;
		var ajaxCache = Array();

		TREE.option = {
			drag:		true,
			animate:	false,
			autoclose:	false,
			speed:		'fast',
			afterAjax:	false,
			afterMove:	false,
			afterClick:	false,
			afterDblClick:	false,
			// added by Erik Dohmen (2BinBusiness.nl) to make context menu cliks available
			afterContextMenu:	false,
			docToFolderConvert:false,
			selectRoot : false
		};
		TREE.option = $.extend(TREE.option,opt);
		$.extend(this, {getSelected: function(){
			return $('span.active', this).parent();
		}});
		TREE.closeNearby = function(obj)
		{
			$(obj).siblings().filter('.folder-open, .folder-open-last').each(function(){
				var childUl = $('>ul',this);
				var className = this.className;
				this.className = className.replace('open','close');
				if(TREE.option.animate)
				{
					childUl.animate({height:"toggle"},TREE.option.speed);
				}else{
					childUl.hide();
				}
			});
		};
		TREE.nodeToggle = function(obj)
		{	
			var childUl = $('>ul',obj);
			if(childUl.is(':visible')){
				obj.className = obj.className.replace('open','close');
				
				if(TREE.option.animate)
				{
					childUl.animate({height:"toggle"},TREE.option.speed);
				}else{
					childUl.hide();
				}
			}else{
				obj.className = obj.className.replace('close','open');
				if(TREE.option.animate)
				{
					childUl.animate({height:"toggle"},TREE.option.speed, function(){
						if(TREE.option.autoclose)TREE.closeNearby(obj);
						if(childUl.is('.ajax'))TREE.setAjaxNodes(childUl, obj.id);
					});
				}else{
					childUl.show();
					if(TREE.option.autoclose)TREE.closeNearby(obj);
					if(childUl.is('.ajax'))TREE.setAjaxNodes(childUl, obj.id);
				}
			}
			return true;
		};
		TREE.setAjaxNodes = function(node, parentId, callback)
		{
			if($.inArray(parentId,ajaxCache) == -1){
				ajaxCache[ajaxCache.length]=parentId;
				var url = $.trim($('>li', node).text());
				if(url && url.indexOf('url:'))
				{
					url=$.trim(url.replace(/.*\{url:(.*)\}/i ,'$1'));
					$.ajax({
						type: "GET",
						url: url,
						contentType:'html',
						cache:false,
						success: function(responce){
							node.removeAttr('class');
							node.html(responce);
							$.extend(node,{url:url});
							TREE.setTreeNodes(node, true);								
							
							//add by shenyinjie@shinetechnology.com;2009-12-8;增加对复选框的处理
							//alert("html=" + node.html());//ul包含的html
							
							//操作上级：当父节点被选中时，所有子节点均被选中，当父节点取消选中时，所有子节点均取消选中
							//通过操作node来获取checkbox的选中/取消选中状态，在进行Ajax加载时触发，Ajax加载时只加载一级，所以无需循环
							if($(">:checkbox",node.parent()).attr("checked") == true){
								$(":checkbox",node).attr("checked", true);
							}
							if($(">:checkbox",node.parent()).attr("checked") == false){
								$(":checkbox",node).attr("checked", false);
							}
							
							
							/**
							 *	给checkbox绑定onclick事件
							 * 
							 *	操作节点时:
							 *	一、对父节点的处理：所有当前节点的同级checkbox都被选中时，选中父节点;当所有当前节点的同级checkbox都取消选中时，父节点也取消选中
							 *	二、对子节点的处理,分两种情况：
							 *	  (1)当前节点是文件夹时,选中当前节点，级联选中当前节点下属的所有节点;
							 *	　　(2)当前节点是文件时,只选中当前节点
							 *
							 */
							$(":checkbox").click(function(){
								var oChk = this;
								if(this.checked){
									//判断父节点是否应该被选中									
									while(oChk){
										var b = true;
										$(oChk).parent().parent().children().children(">:checkbox").each(function(){//遍历同级的其他checkbox,看其他checkbox是否都处于选中，是，则选中父级
											if($(this).attr("checked") == false){
												b = false;
												return false;
											}
											
										});
										if(b){
											$(oChk).parent().parent().parent().children(":checkbox").attr("checked", true);
										}
										oChk = $(oChk).parent().parent().parent().children(":checkbox").get(0);
									}
									
									//子节点被选中
									if($(this).parent().attr("class").indexOf("doc") == -1){//只有文件夹才有级联选中
										$(":checkbox",($(this).parent().children("ul").get(0))).each(function(){//li ul li ">:checkbox"
											$(this).attr("checked", true);
										});
									}
								}
								else{
									//判断父节点是否应该被取消选中				
									while(oChk){
										var b = false;
										$(oChk).parent().parent().children().children(">:checkbox").each(function(){//遍历同级的其他checkbox,看其他checkbox是否都处于选中，是，则选中父级
											if($(this).attr("checked") == true){
												b = true;
												return false;
											}
											
										});
										if(!b){
											$(oChk).parent().parent().parent().children(":checkbox").attr("checked", false);
										}
										oChk = $(oChk).parent().parent().parent().children(":checkbox").get(0);
									}
									
									//子节点被取消选中
									if($(this).parent().attr("class").indexOf("doc") == -1){//只有文件夹才有级联取消选中
										$(":checkbox",($(this).parent().children("ul").get(0))).each(function(){//li ul li ">:checkbox"
											$(this).attr("checked", false);
										});
									}
								}
							});
							//add by shenyinjie@shinetechnology.com;2009-12-8;增加对复选框的处理　end
							
							if(typeof TREE.option.afterAjax == 'function')
							{
								TREE.option.afterAjax(node);
							}
							if(typeof callback == 'function')
							{
								callback(node);
							}
						}
					});
				}
				
			}
		};
		TREE.setTreeNodes = function(obj, useParent){
			obj = useParent? obj.parent():obj;
			var findexp = TREE.option.selectRoot ? '>span,li>span' : 'li>span';
			$(findexp, obj).addClass('text')
			.bind('selectstart', function() {
				return false;
			}).click(function(){
				$('.active',TREE).attr('class','text');
				if(this.className=='text')
				{
					this.className='active';
				}
				if(typeof TREE.option.afterClick == 'function')
				{
					TREE.option.afterClick($(this).parent());
				}
				return false;
			}).dblclick(function(){
				mousePressed = false;
				TREE.nodeToggle($(this).parent().get(0));
				if(typeof TREE.option.afterDblClick == 'function')
				{
					TREE.option.afterDblClick($(this).parent());
				}
				return false;
				// added by Erik Dohmen (2BinBusiness.nl) to make context menu actions
				// available
			}).bind("contextmenu",function(){
				$('.active',TREE).attr('class','text');
				if(this.className=='text')
				{
					this.className='active';
				}
				if(typeof TREE.option.afterContextMenu == 'function')
				{
					TREE.option.afterContextMenu($(this).parent());
				}
				return false;
			}).mousedown(function(event){
				mousePressed = true;
				cloneNode = $(this).parent().clone();
				var LI = $(this).parent();
				if(TREE.option.drag)
				{
					$('>ul', cloneNode).hide();
					$('body').append('<div id="drag_container"><ul></ul></div>');
					$('#drag_container').hide().css({opacity:'0.8'});
					$('#drag_container >ul').append(cloneNode);
					$("<img>").attr({id	: "tree_plus",src	: "webui/tree/images/plus.gif"}).css({width: "7px",display: "block",position: "absolute",left	: "5px",top: "5px", display:'none'}).appendTo("body");
					$(document).bind("mousemove", {LI:LI}, TREE.dragStart).bind("mouseup",TREE.dragEnd);
				}
				return false;
			}).mouseup(function(){
				if(mousePressed && mouseMoved && dragNode_source)
				{
					TREE.moveNodeToFolder($(this).parent());
				}
				TREE.eventDestroy();
			});
			$('li', obj).each(function(i){
				var className = this.className;
				var open = false;
				var cloneNode=false;
				var LI = this;
				var childNode = $('>ul',this);
				if(childNode.size()>0){
					var setClassName = 'folder-';
					if(className && className.indexOf('open')>=0){
						setClassName=setClassName+'open';
						open=true;
					}else{
						setClassName=setClassName+'close';
					}
					this.className = setClassName + ($(this).is(':last-child')? '-last':'');

					if(!open || className.indexOf('ajax')>=0)childNode.hide();

					TREE.setTrigger(this);
				}else{
					var setClassName = 'doc';
					this.className = setClassName + ($(this).is(':last-child')? '-last':'');
				}
			}).before('<li class="line">&nbsp;</li>')
			.filter(':last-child').after('<li class="line-last"></li>');
			TREE.setEventLine($('.line, .line-last', obj));
		};
		TREE.setTrigger = function(node){
			var htmlImg = '<img class="trigger" src="webui/tree/images/spacer.gif" border=0>';
			if($(">:checkbox",node).length > 0){//有checkbox在checkbox前加htmlImg,这样才可以做到点击+,-符号展开/收缩节点　modify by shenyinjie@shinetechnology.com;2009-12-08
				$('>:checkbox',node).before(htmlImg);
			} else{
				$('>span',node).before(htmlImg);
			}
			
			var trigger = $('>.trigger', node);
			trigger.click(function(event){
				TREE.nodeToggle(node);
				
			});
			if(!$.browser.msie)
			{
				trigger.css('float','left');
			}
		};
		TREE.dragStart = function(event){
			var LI = $(event.data.LI);
			if(mousePressed)
			{
				mouseMoved = true;
				if(dragDropTimer) clearTimeout(dragDropTimer);
				if($('#drag_container:not(:visible)')){
					$('#drag_container').show();
					LI.prev('.line').hide();
					dragNode_source = LI;
				}
				$('#drag_container').css({position:'absolute', "left" : (event.pageX + 5), "top": (event.pageY + 15) });
				if(LI.is(':visible'))LI.hide();
				var temp_move = false;
				if(event.target.tagName.toLowerCase()=='span' && $.inArray(event.target.className, Array('text','active','trigger'))!= -1)
				{
					var parent = event.target.parentNode;
					var offs = $(parent).offset({scroll:false});
					var screenScroll = {x : (offs.left - 3),y : event.pageY - offs.top};
					var isrc = $("#tree_plus").attr('src');
					var ajaxChildSize = $('>ul.ajax',parent).size();
					var ajaxChild = $('>ul.ajax',parent);
					screenScroll.x += 19;
					screenScroll.y = event.pageY - screenScroll.y + 5;

					if(parent.className.indexOf('folder-close')>=0 && ajaxChildSize==0)
					{
						if(isrc.indexOf('minus')!=-1)$("#tree_plus").attr('src','webui/tree/images/plus.gif');
						$("#tree_plus").css({"left": screenScroll.x, "top": screenScroll.y}).show();
						dragDropTimer = setTimeout(function(){
							parent.className = parent.className.replace('close','open');
							$('>ul',parent).show();
						}, 700);
					}else if(parent.className.indexOf('folder')>=0 && ajaxChildSize==0){
						if(isrc.indexOf('minus')!=-1)$("#tree_plus").attr('src','webui/tree/images/plus.gif');
						$("#tree_plus").css({"left": screenScroll.x, "top": screenScroll.y}).show();
					}else if(parent.className.indexOf('folder-close')>=0 && ajaxChildSize>0)
					{
						mouseMoved = false;
						$("#tree_plus").attr('src','webui/tree/images/minus.gif');
						$("#tree_plus").css({"left": screenScroll.x, "top": screenScroll.y}).show();

						$('>ul',parent).show();
						/*
							Thanks for the idea of Erik Dohmen
						*/
						TREE.setAjaxNodes(ajaxChild,parent.id, function(){
							parent.className = parent.className.replace('close','open');
							mouseMoved = true;
							$("#tree_plus").attr('src','webui/tree/images/plus.gif');
							$("#tree_plus").css({"left": screenScroll.x, "top": screenScroll.y}).show();
						});

					}else{
						if(TREE.option.docToFolderConvert)
						{
							$("#tree_plus").css({"left": screenScroll.x, "top": screenScroll.y}).show();
						}else{
							$("#tree_plus").hide();
						}
					}
				}else{
					$("#tree_plus").hide();
				}
				return false;
			}
			return true;
		};
		TREE.dragEnd = function(){
			if(dragDropTimer) clearTimeout(dragDropTimer);
			TREE.eventDestroy();
		};
		TREE.setEventLine = function(obj){
			obj.mouseover(function(){
				if(this.className.indexOf('over')<0 && mousePressed && mouseMoved)
				{
					this.className = this.className.replace('line','line-over');
				}
			}).mouseout(function(){
				if(this.className.indexOf('over')>=0)
				{
					this.className = this.className.replace('-over','');
				}
			}).mouseup(function(){
				if(mousePressed && dragNode_source && mouseMoved)
				{
					dragNode_destination = $(this).parents('li:first');
					TREE.moveNodeToLine(this);
					TREE.eventDestroy();
				}
			});
		};
		TREE.checkNodeIsLast = function(node)
		{
			if(node.className.indexOf('last')>=0)
			{
				var prev_source = dragNode_source.prev().prev();
				if(prev_source.size()>0)
				{
					prev_source[0].className+='-last';
				}
				node.className = node.className.replace('-last','');
			}
		};
		TREE.checkLineIsLast = function(line)
		{
			if(line.className.indexOf('last')>=0)
			{
				var prev = $(line).prev();
				if(prev.size()>0)
				{
					prev[0].className = prev[0].className.replace('-last','');
				}
				dragNode_source[0].className+='-last';
			}
		};
		TREE.eventDestroy = function()
		{
			// added by Erik Dohmen (2BinBusiness.nl), the unbind mousemove TREE.dragStart action
			// like this other mousemove actions binded through other actions ain't removed (use it myself
			// to determine location for context menu)
			$(document).unbind('mousemove',TREE.dragStart).unbind('mouseup').unbind('mousedown');
			$('#drag_container, #tree_plus').remove();
			if(dragNode_source)
			{
				$(dragNode_source).show().prev('.line').show();
			}
			dragNode_destination = dragNode_source = mousePressed = mouseMoved = false;
			//ajaxCache = Array();
		};
		TREE.convertToFolder = function(node){
			node[0].className = node[0].className.replace('doc','folder-open');
			node.append('<ul><li class="line-last"></li></ul>');
			TREE.setTrigger(node[0]);
			TREE.setEventLine($('.line, .line-last', node));
		};
		TREE.convertToDoc = function(node){
			$('>ul', node).remove();
			$('img', node).remove();
			node[0].className = node[0].className.replace(/folder-(open|close)/gi , 'doc');
		};
		TREE.moveNodeToFolder = function(node)
		{
			if(!TREE.option.docToFolderConvert && node[0].className.indexOf('doc')!=-1)
			{
				return true;
			}else if(TREE.option.docToFolderConvert && node[0].className.indexOf('doc')!=-1){
				TREE.convertToFolder(node);
			}
			TREE.checkNodeIsLast(dragNode_source[0]);
			var lastLine = $('>ul >.line-last', node);
			if(lastLine.size()>0)
			{
				TREE.moveNodeToLine(lastLine[0]);
			}
		};
		TREE.moveNodeToLine = function(node){
			TREE.checkNodeIsLast(dragNode_source[0]);
			TREE.checkLineIsLast(node);
			var parent = $(dragNode_source).parents('li:first');
			var line = $(dragNode_source).prev('.line');
			$(node).before(dragNode_source);
			$(dragNode_source).before(line);
			node.className = node.className.replace('-over','');
			var nodeSize = $('>ul >li', parent).not('.line, .line-last').filter(':visible').size();
			if(TREE.option.docToFolderConvert && nodeSize==0)
			{
				TREE.convertToDoc(parent);
			}else if(nodeSize==0)
			{
				parent[0].className=parent[0].className.replace('open','close');
				$('>ul',parent).hide();
			}

			// added by Erik Dohmen (2BinBusiness.nl) select node
			if($('span:first',dragNode_source).attr('class')=='text')
			{
				$('.active',TREE).attr('class','text');
				$('span:first',dragNode_source).attr('class','active');
			}

			if(typeof(TREE.option.afterMove) == 'function')
			{
				var pos = $(dragNode_source).prevAll(':not(.line)').size();
				TREE.option.afterMove($(node).parents('li:first'), $(dragNode_source), pos);
			}
		};

		TREE.addNode = function(id, text, callback)
		{
			var temp_node = $('<li><ul><li id="'+id+'"><span>'+text+'</span></li></ul></li>');
			TREE.setTreeNodes(temp_node);
			dragNode_destination = TREE.getSelected();
			dragNode_source = $('.doc-last',temp_node);
			TREE.moveNodeToFolder(dragNode_destination);
			temp_node.remove();
			if(typeof(callback) == 'function')
			{
				callback(dragNode_destination, dragNode_source);
			}
		};
		TREE.delNode = function(callback)
		{
			dragNode_source = TREE.getSelected();
			
			var parentNode = dragNode_source.parent().parent();
			
			TREE.checkNodeIsLast(dragNode_source[0]);
			dragNode_source.prev().remove();
			dragNode_source.remove();
			
			//add by zsy 没有子节点时转为文件
			var childNode = $('>ul:has(span)',parentNode);
			if (childNode.size() == 0) { 
				TREE.convertToDoc(parentNode);
			}
			
			if(typeof(callback) == 'function')
			{
				callback(dragNode_destination);
			}
		};

		TREE.init = function(obj)
		{
			TREE.setTreeNodes(obj, false);
		};
		TREE.init(ROOT);
		
		
		
		
		//修改节点名称//id为空时不修改 add by zsy
		TREE.modifyNode = function(id, text, callback)
		{
			var activeSpan = $('span.active', this);
			activeSpan.html(text);
			var selectedNode = activeSpan.parent();
			if (id) {
				selectedNode.attr("id", id);
			}
			if(typeof(callback) == 'function')
			{
				callback(selectedNode);
			}
		};
		
		//取得当前节点的父节点 add by zsy
		TREE.getParentNode = function()
		{
			var node = TREE.getSelected();
			if(node.attr('class') == 'root') {
				return ROOT;
			} else {
				return node.parent().parent();
			}
		};
		
		//展开节点parm为节点ID或JQuery对像都可以 add by zsy
		TREE.openNode = function(parm, callback)
		{
			var node = (typeof(parm) == 'string') ? $('#' + parm, this) : parm;
			
			var obj = node[0];
			var childUl = $('>ul',obj);
			if(childUl.size() > 0 && !childUl.is(':visible')){
				obj.className = obj.className.replace('close','open');
				if(TREE.option.animate)
				{
					childUl.animate({height:"toggle"},TREE.option.speed, function(){
						if(TREE.option.autoclose)TREE.closeNearby(obj);
						if(childUl.is('.ajax')) {
							TREE.setAjaxNodes(childUl, obj.id, callback);
						} else if(typeof(callback) == 'function') {
							
							callback(node, true);
						}
					});
				}else{
					childUl.show();
					if(TREE.option.autoclose)TREE.closeNearby(obj);
					if(childUl.is('.ajax')) {
						TREE.setAjaxNodes(childUl, obj.id, callback);
					} else if(typeof(callback) == 'function') {
						callback(node, true);
					}
				}
			} else {
				if(typeof(callback) == 'function')
				{
					callback(node, true);
				}
			}
		};
		
		//刷新节点 add by zsy
		TREE.refreshNode = function(parentNode, ajaxUrl, callback)
		{
			if (!parentNode) {
				parentNode = TREE.getSelected();
			}
			$('>ul', parentNode).remove();
		  	parentNode.append("<ul class='ajax'><li>{url:" + ajaxUrl + "}</li></ul>");
		  	TREE.setTreeNodes(parentNode, false);
		  	$(ajaxCache).each(function(i){//移除缓存
		  	//	if (ajaxCache[i] == parentNode.attr("id")) {
		  			ajaxCache[i] = null;

		  	//	}
		  	});
		  	TREE.openNode(parentNode, callback);
		};
		
		//选中节点（只能是已加载的）节点ID路径字符串，如：id22/id33/id44 add by zsy
		TREE.selectNode = function(nodePath, firstId) 
		{
			if (firstId) {
				TREE.openNode($("#" + firstId, this),function(){
					TREE.selectNode(nodePath);
				});
			} else {
				var index = nodePath.indexOf("/");
				if (index == -1) {//只有一级节点
				 	var node = $('#'+nodePath,this);
					$('span:first',node).click();
					return;
				}
				var nodeId = nodePath.substring(0, index);
				var elseIds = nodePath.substring(index + 1, nodePath.length);
				TREE.selectNode(elseIds, nodeId);
			}
		}
		
		//当前节点同级内，向上移一位 add by zsy
		TREE.moveUp = function(callback)
		{
			var node = TREE.getSelected();
			var target = node.prevAll('li:has(span):first');
			if(target.size() == 0){//是最前面一个
				return;
			}
			var line = node.prev('li');
    		target.before(node);
			target.before(line);
			
			if(typeof(callback) == 'function')
			{
				callback(node, target);
			}
		};
		
		//当前节点同级内，移到最上面 add by zsy
		TREE.moveTop = function(callback)
		{
			var node = TREE.getSelected();
			var target = node.prevAll('li:has(span):last');
			if(target.size() == 0){//是最前面一个
				return;
			}
			var line = node.prev('li');
       		target.before(node);
			target.before(line);
			
			if(typeof(callback) == 'function')
			{
				callback(node, target);
			}
		};
		
		//当前节点同级内，向下移一位 add by zsy
		TREE.moveDown = function(callback)
		{
			var node = TREE.getSelected();
			var target = node.nextAll('li:has(span):first');
			if(target.size() == 0){//是最后一个
				return;
			}
			var line = node.prev('li');
       		target.after(node);
			target.after(line);	
			
			if(typeof(callback) == 'function')
			{
				callback(node, target);
			}
		};
		
		//当前节点同级内，移到最底下 add by zsy
		TREE.moveBottom = function(callback)
		{
			var node = TREE.getSelected();
			var target = node.nextAll('li:has(span):last');
			if(target.size() == 0){//是最后一个
				return;
			}
			var line = node.prev('li');
       		target.after(node);
			target.after(line);	
			
			if(typeof(callback) == 'function')
			{
				callback(node, target);
			}
		};
		
	});
}